#include "simodo/lsp-client/ClientParams.h"

#include "simodo/inout/convert/functions.h"

using namespace simodo::inout;

namespace simodo::lsp
{

ClientParams parseClientParams(std::shared_ptr<variable::Object> params_object)
{
    ClientParams p;

    const variable::Value & processId_value = params_object->find(u"processId");
    if (processId_value.type() == variable::ValueType::Int)
        p.processId = processId_value.getInt();

    const variable::Value & locale_value = params_object->find(u"locale");
    if (locale_value.type() == variable::ValueType::String)
        p.locale = toU8(locale_value.getString());

    const variable::Value & rootPath_value = params_object->find(u"rootPath");
    if (rootPath_value.type() == variable::ValueType::String)
        p.rootPath = toU8(rootPath_value.getString());

    const variable::Value & rootUri_value = params_object->find(u"rootUri");
    if (rootUri_value.type() == variable::ValueType::String)
        p.rootUri = toU8(rootUri_value.getString());

    const variable::Value & capabilities_value = params_object->find(u"capabilities");
    if (capabilities_value.type() == variable::ValueType::Object)
        p.cap = parseClientCapabilities(capabilities_value.getObject());

    const variable::Value & trace_value = params_object->find(u"trace");
    if (trace_value.type() == variable::ValueType::String) {
        if (trace_value.getString() == u"messages")
            p.trace = TraceValue::messages;
        else if (trace_value.getString() == u"verbose")
            p.trace = TraceValue::verbose;
    }

    return p;
}

Capabilities parseClientCapabilities(std::shared_ptr<variable::Object> cap_object)
{
    Capabilities cap;

    const variable::Value & textDocument_value = cap_object->find(u"textDocument");
    if (textDocument_value.type() == variable::ValueType::Object)
        cap.doc = parseTextDocument(textDocument_value.getObject());

    return cap;
}

TextDocument parseTextDocument(std::shared_ptr<variable::Object> doc_object)
{
    TextDocument doc;

    const variable::Value & hover_value = doc_object->find(u"hover");
    if (hover_value.type() == variable::ValueType::Object)
        doc.hover = parseHoverClientCapabilities(hover_value.getObject());

    return doc;
}

HoverClientCapabilities parseHoverClientCapabilities(std::shared_ptr<simodo::variable::Object> hover_object)
{
    HoverClientCapabilities hover;

    const variable::Value & dynamicRegistration_value = hover_object->find(u"dynamicRegistration");
    if (dynamicRegistration_value.type() == variable::ValueType::Bool)
        hover.dynamicRegistration = dynamicRegistration_value.getBool();

    const variable::Value & contentFormat_value = hover_object->find(u"contentFormat");
    if (contentFormat_value.type() == variable::ValueType::Array)
        for(const variable::Value & format_value : contentFormat_value.getArray()->values())
            if (format_value.type() == variable::ValueType::String)
                hover.contentFormat.insert(toU8(format_value.getString()));

    return hover;
}

}
